/**
 * Copyright (C) 2010-2012 Regis Montoya (aka r3gis - www.r3gis.fr)
 * This file is part of CSipSimple.
 *
 *  CSipSimple is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *  If you own a pjsip commercial license you can also redistribute it
 *  and/or modify it under the terms of the GNU Lesser General Public License
 *  as an android library.
 *
 *  CSipSimple is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with CSipSimple.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * This file contains relicensed code from Apache copyright of 
 * Copyright (C) 2006 The Android Open Source Project
 */

package com.cloudptt.api.product.ringer;

import java.io.IOException;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.AssetFileDescriptor;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.preference.PreferenceManager;

import com.cloudptt.api.pjsip.api.SipConfigManager;
import com.cloudptt.api.product.log.Log;

/**
 * Sound manager for the Phone app.
 */
public class SoundPlayer implements MediaPlayer.OnPreparedListener,MediaPlayer.OnErrorListener{
	private static final String THIS_FILE = "SoundPlayer";

	HandlerThread ringerThread;
	Context context;
	private SoundPlayerWorkerHandler soundPlayerWorker;
	//    private MediaPlayer.OnPreparedListener prepareListener;
	//    private MediaPlayer.OnCompletionListener completeListener ;
	//    private MediaPlayer.OnErrorListener errListener ;

	private MediaPlayer mediaPlayer ;

	public SoundPlayer(Context aContext,MediaPlayer.OnCompletionListener completeListener ) {
		context = aContext;
		mediaPlayer = new MediaPlayer();
		//        this.completeListener = completeListener;
		//        mediaPlayer.setOnCompletionListener( completeListener );
		SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(aContext);
		String streamType = sp.getString( SipConfigManager.STREAM_TYPE, Integer.toString( AudioManager.STREAM_MUSIC) );
		mediaPlayer.setAudioStreamType( Integer.parseInt( streamType ) );
		mediaPlayer.setOnPreparedListener( SoundPlayer.this );
		mediaPlayer.setOnCompletionListener( completeListener );
		mediaPlayer.setOnErrorListener(SoundPlayer.this);

		ringerThread = new HandlerThread("RingerThread");
		ringerThread.start();
		soundPlayerWorker = new SoundPlayerWorkerHandler(ringerThread.getLooper());
	}

	public void play(int type) {
		Log.v(THIS_FILE, "==> play() called..." + type);
		synchronized (this) {
			int soundId = getSourceByType( type );
			if( -1 == soundId){
				Log.e( THIS_FILE, "Invalid type=" +type );
				return;
			}
			soundPlayerWorker.setSoundId( soundId );
			soundPlayerWorker.startSoundPlay();
		}
	}

	/**
	 * @return true if we're playing a ringtone and/or vibrating
	 *     to indicate that there's an incoming call.
	 *     ("Ringing" here is used in the general sense.  If you literally
	 *     need to know if we're playing a ringtone or vibrating, use
	 *     isRingtonePlaying() or isVibrating() instead.)
	 */
	public boolean isPlaying() {
		return (!soundPlayerWorker.isStopped() );
	}

	public void stopSoundPlay() {
		synchronized (this) {
			Log.v(THIS_FILE, "==> stopSoundPlay...");
			stopPlay();
		}
	}


	private void stopPlay() {
		soundPlayerWorker.askStop();
	}

	/**
	 * Thread worker class that handles the task playing ringtone
	 */
	private class SoundPlayerWorkerHandler extends Handler {
		public static final int PROGRESS_SOUND = 0;
		private Boolean askedStopped = true;
		private int soundId = -1;

		public SoundPlayerWorkerHandler(Looper looper) {
			super(looper);
		}

		public void startSoundPlay() {
			Log.v(THIS_FILE, "startSoundPlay");
			Message msg = soundPlayerWorker.obtainMessage(SoundPlayerWorkerHandler.PROGRESS_SOUND);
			msg.arg1 = SoundPlayerWorkerHandler.PROGRESS_SOUND;
			soundPlayerWorker.sendMessageDelayed( msg,150 );
		}

		/**
		 * @param ringtone
		 */
		public synchronized void setSoundId(int soundId) {
			this.soundId = soundId;
			askedStopped = false;
		}

		public synchronized void askStop() {
			Log.v( THIS_FILE, "askStop" );
			askedStopped = true;
		}

		public synchronized boolean isStopped() {
			Log.v( THIS_FILE, "askedStopped=" + askedStopped );
			return askedStopped ;
		}

		public void handleMessage(Message msg) {
			//            if(mediaPlayer == null) {
			//                return;
			//            }
			Log.v(THIS_FILE, "handleMessage");
			if (msg.arg1 == PROGRESS_SOUND) {
				//                synchronized (askedStopped) {
				//                    if(askedStopped) {
				//                        return;
				//                    }
				//                }

				//                if( !mediaPlayer.isPlaying( ) )
				//				{
				try 
				{
					if(mediaPlayer != null)
					{
						mediaPlayer.reset();
					}
					
					AssetFileDescriptor fileDesc = context.getResources().openRawResourceFd(soundId);
					if( null == fileDesc)
					{
						Log.e( THIS_FILE, "Can not get fileDesc=" +soundId );
						return;
					}
					Log.v( THIS_FILE, "fileDesc=" + fileDesc.toString( ) );
					

					mediaPlayer.setDataSource( fileDesc.getFileDescriptor( ),fileDesc.getStartOffset( ),
							fileDesc.getLength( ));
					fileDesc.close( );
					mediaPlayer.setVolume( 0.4f, 0.4f );

					Log.v(THIS_FILE, "handleMessage start begin");
					mediaPlayer.prepareAsync();
					
					Log.v(THIS_FILE, "handleMessage start end");
				}catch (IllegalArgumentException e) {
					e.printStackTrace();
					return;
				} catch (IllegalStateException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
				//				}

				//                Message msgBis = ringerWorker.obtainMessage(RingWorkerHandler.PROGRESS_RING);
				//                msg.arg1 = RingWorkerHandler.PROGRESS_RING;
				//                ringerWorker.sendMessageDelayed(msgBis, 100);
			}
		}
	}

	public final static int Type_On = 0;
	public final static int Type_Off = 1;
	public final static int Type_Accept = 2;
//	private int onSound,offSound,acceptSound = -1;  

	public void soundRing(int type)
	{
		Log.v(THIS_FILE, "soundRing type is " + type);
		int soundSource = getSourceByType(type);
		if( -1 == soundSource)
		{
			return;
		}
	}

	private int getSourceByType(int type)
	{
		//		if(Type_On == type)
		//		{
		//			return R.raw.on;
		//		}
		//		else if(Type_Off == type)
		//		{
		//			return R.raw.off;
		//		}
		//		else if(Type_Accept == type)
		//		{
		//			return R.raw.accept;
		//		}
		//		return -1;
		return type;
	}

	@Override
	public boolean onError(MediaPlayer mp, int what, int extra) {
		Log.d(THIS_FILE, "OnError - Error code: " + what + " Extra code: " + extra);
		return false;
	}

	@Override
	public void onPrepared(MediaPlayer arg0) {
		// TODO Auto-generated method stub
		Log.d(THIS_FILE, "onPrepared");
		mediaPlayer.start( );
	}
}
